﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using OnCommon;
using OnLineLogFileComm;
using System.IO;
using System.Net;


namespace OnLineLogFileServer
{
    public partial class OnLineServer : Form
    {
        public OnLineServer()
        {
            InitializeComponent();
        }
        SocketTcpServer server;
        static Dictionary<string, FileStream> dic = new Dictionary<string, FileStream>();
        static Dictionary<string, string> dic_file = new Dictionary<string, string>();

        public static void ClearChaceFile(IEnumerable<IPEndPoint> address)
        {
            //obj.IPEndPoint.Address.ToString() + "." + obj.IPEndPoint.Port;
            if (address == null || address.Count() == 0)
            {
                MessageBox.Show("清楚失败");
            }
            dic.Keys
                .Except(address.Select(p => p.Address.ToString() + "." + p.Port))
                .ToList().ForEach(p =>
            {
                if (dic.ContainsKey(p))
                {
                    SendFileSuccess(p);
                }
            });

        }
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                server = new SocketTcpServer();
                server.Listen(20141, 20);
            }
            catch (Exception ex)
            {
                InvMsg(ex.Message);
            }
            server.OnCompleted += server_OnCompleted;
            this.label1.Text = "已启动。。。。。。。。。port:20141";
            this.button1.Enabled = false;
        }

        void server_OnCompleted(SocketTcpData obj)
        {
            if (OnLineClient.Instance.HasUpdate)
            {
                OnLineClient.Instance.Set(obj.IPEndPoint);
            }
            try
            {
                switch (obj.DataType)
                {
                    case PacketType.String:
                        break;
                    case PacketType.Binary:
                        TranBinary(obj);
                        break;
                    case PacketType.Complex:
                        TranComplex(obj);
                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                InvMsg(ex.Message);
            }
        }

        private void TranBinary(SocketTcpData obj)
        {
            var dicKey = obj.IPEndPoint.Address.ToString() + "." + obj.IPEndPoint.Port;
            if (dic.ContainsKey(dicKey))
            {
                this.InvMsg(dicKey + "。收到" + obj.GetByteData().Length / 1024 + "kb，" + obj.GetByteData().Length);
                dic[dicKey].Write(obj.GetByteData(), 0, obj.GetByteData().Length);
            }
        }
        //对象传输，解析命令
        private void TranComplex(SocketTcpData obj)
        {
            var dicKey = obj.IPEndPoint.Address.ToString() + "." + obj.IPEndPoint.Port;
            var command = obj.GetObjData<Command>();
            InvMsg(command.CommandType.ToString() + " : " + obj.GetStringData() + "：" + dicKey);

            switch (command.CommandType)
            {
                case OnLineLogFileComm.CommandType.SendFileName:
                    SendFileName(obj, command, dicKey);
                    break;
                case OnLineLogFileComm.CommandType.SendFileSuccess://文件传输完成。清理资源
                    SendFileSuccess(dicKey);
                    break;
                case OnLineLogFileComm.CommandType.CheckUpdateClient:
                    CheckUpdateClient(obj, command);
                    break;
                case OnLineLogFileComm.CommandType.CheckUpdateClientFiles:
                    CheckUpdateClientFiles(obj);
                    break;
                case OnLineLogFileComm.CommandType.UpdateClientFile:
                    var fileName = command.Data.ToString();
                    var clientBinPath = Path.Combine(Environment.CurrentDirectory, "client_exe");
                    var filePath = Path.Combine(clientBinPath, fileName);
                    var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                    obj.Send(fs);
                    fs.Close();
                    fs.Dispose();
                    break;
            }
        }

        private void CheckUpdateClientFiles(SocketTcpData obj)
        {
            var clientBinPath = Path.Combine(GetAssemblyPath(), "client_exe");
            InvMsg(clientBinPath);
            var isex = Directory.Exists(clientBinPath).ToString();
            var isexf = File.Exists(clientBinPath + "\\OnLineLogFileClient.exe");
            var isc = Directory.GetFileSystemEntries(clientBinPath).Length;
            InvMsg("isex:" + isex + ",isexf:" + isexf + ",isc:" + isc);
            var files = Directory.GetFileSystemEntries(clientBinPath).Select(p => Path.GetFileName(p)).ToList();
            obj.Send(files);
        }

        private void CheckUpdateClient(SocketTcpData obj, Command command)
        {
            var clientVer = command.Data.JsonToObj<Version>();
            var serverVer = this.GetType().Assembly.GetName().Version;
            InvMsg("ClientVer:" + clientVer + "ServerVer:" + serverVer);
            if (clientVer != serverVer)
                obj.Send(new { status = true });
            else
                obj.Send(new { status = false });
        }

        private static void SendFileSuccess(string dicKey)
        {
            if (dic.ContainsKey(dicKey))
            {
                var fs = dic[dicKey];
                lock (dic)
                {
                    dic.Remove(dicKey);
                }
                if (dic_file.ContainsKey(fs.Name))
                {
                    lock (dic_file)
                    {
                        dic_file.Remove(fs.Name);
                    }
                }
                fs.Flush();
                fs.Dispose();
            }
        }

        private void SendFileName(SocketTcpData obj, Command command, string dicKey)
        {
            var filePath = "";
            //@"d:\vjsadmin_logs\" + obj.IPEndPoint.Address.ToString() + "_" + command.Data;

            if (command.Data.Contains("callTiming"))
            {
                //192.168.160.227_callTiming_04_11_16_0

                //04_11_16
                var date = command.Data.Substring("callTiming_".Length, 5);
                var m = date.Substring(0, 2);
                var d = date.Substring(3, 2);
                var path = @"d:\vjsadmin_logs\callTiming\" + m + "\\" + d + "\\";

                filePath = path + obj.IPEndPoint.Address.ToString() +
                      "_" + command.Data;
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
            }
            else
            {
                //aaflog
                var date = command.Data.Substring("Aaf2014".Length, 4);
                var m = date.Substring(0, 2);
                var d = date.Substring(2, 2);
                var path = @"d:\vjsadmin_logs\aaflogs\" + m + "\\" + d + "\\";
                filePath = path + obj.IPEndPoint.Address.ToString() +
                     "_" + command.Data;
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
            }
            //192.168.160.59_Aaf20140419_0.log

            if (!dic_file.ContainsKey(filePath))
            {
                lock (dic_file)
                {
                    dic_file.Add(filePath, dicKey);
                }
                FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Read, 512);
                lock (dic)
                {
                    dic.Add(dicKey, fs);
                }
            }
            else
            {

                var oldDicKey = dic_file[filePath];
                dic_file[filePath] = dicKey;

                var fs = dic[oldDicKey];
                lock (dic)
                {
                    dic.Remove(oldDicKey);
                    dic.Add(dicKey, fs);
                }

            }


            InvMsg("收到文件：" + filePath);
            obj.Send(new { len = dic[dicKey].Position });
        }

        void InvMsg(string msg)
        {
            this.Invoke(new Action(() =>
            {
                if (this.richTextBox1.TextLength > 200000)
                {
                    this.richTextBox1.Clear();
                }
                this.richTextBox1.AppendText(msg + Environment.NewLine);
                this.richTextBox1.ScrollToCaret();
                this.richTextBox1.Focus();
            }));
        }

        private void button2_Click(object sender, EventArgs e)
        {
            new ShowOnLineClient().Show();
        }

        private void button3_Click(object sender, EventArgs e)
        {

            new Show(dic, dic_file).Show();
        }
        private static string GetAssemblyPath()
        {
            string l = System.Reflection.Assembly.GetEntryAssembly().Location;

            FileInfo fi = new FileInfo(l);
            Console.WriteLine("==========" + fi.DirectoryName);
            return fi.DirectoryName;
        }

    }
}
